"""
模拟交易所
用于模拟盘交易和测试
"""
from typing import Dict, List, Optional
from datetime import datetime
from src.okx.models import Order, Position, AccountBalance, TradeResult
from src.utils.logger import get_logger

logger = get_logger(__name__)


class MockExchange:
    """
    模拟交易所
    用于回测和模拟盘交易
    """

    def __init__(self, initial_balances: Dict[str, float]):
        """
        初始化

        Args:
            initial_balances: 初始余额 {币种: 余额}
        """
        self.balances = initial_balances.copy()
        self.orders: Dict[str, Order] = {}
        self.positions: List[Position] = []
        self.order_counter = 0
        self.current_prices: Dict[str, float] = {}

    def set_ticker(self, symbol: str, price: float):
        """设置交易对的最新价格"""
        self.current_prices[symbol] = price

    def place_order(self, symbol: str, side: str, order_type: str,
                   quantity: float, price: Optional[float] = None) -> TradeResult:
        """
        下单

        Args:
            symbol: 交易对
            side: 交易方向 (buy/sell)
            order_type: 订单类型 (market/limit)
            quantity: 数量
            price: 价格 (限价单需要)

        Returns:
            TradeResult
        """
        self.order_counter += 1
        order_id = f"MOCK_{self.order_counter}"

        # 获取基础币和报价币
        base, quote = symbol.split('-')

        # 市价单直接成交
        if order_type == "market":
            execution_price = self.current_prices.get(symbol, price or 0)

            if execution_price == 0:
                return TradeResult(
                    success=False,
                    message="无法获取价格"
                )

            # 检查余额
            if side == "buy":
                required_balance = quantity * execution_price
                if self.balances.get(quote, 0) < required_balance:
                    return TradeResult(
                        success=False,
                        message=f"{quote}余额不足"
                    )

                # 执行交易
                self.balances[quote] = self.balances.get(quote, 0) - required_balance
                self.balances[base] = self.balances.get(base, 0) + quantity

            else:  # sell
                if self.balances.get(base, 0) < quantity:
                    return TradeResult(
                        success=False,
                        message=f"{base}余额不足"
                    )

                # 执行交易
                self.balances[base] = self.balances.get(base, 0) - quantity
                self.balances[quote] = self.balances.get(quote, 0) + (quantity * execution_price)

            # 创建订单记录
            order = Order(
                order_id=order_id,
                symbol=symbol,
                order_type=order_type,
                side=side,
                price=price or execution_price,
                quantity=quantity,
                status="filled",
                filled_qty=quantity,
                filled_price=execution_price,
                timestamp=int(datetime.now().timestamp() * 1000)
            )

            self.orders[order_id] = order

            return TradeResult(
                success=True,
                order_id=order_id,
                order=order,
                timestamp=order.timestamp
            )

        # 限价单
        else:  # limit
            if price is None:
                return TradeResult(
                    success=False,
                    message="限价单必须指定价格"
                )

            # 创建待成交订单
            order = Order(
                order_id=order_id,
                symbol=symbol,
                order_type=order_type,
                side=side,
                price=price,
                quantity=quantity,
                status="pending",
                filled_qty=0,
                filled_price=0,
                timestamp=int(datetime.now().timestamp() * 1000)
            )

            self.orders[order_id] = order

            return TradeResult(
                success=True,
                order_id=order_id,
                order=order,
                timestamp=order.timestamp
            )

    def cancel_order(self, symbol: str, order_id: str) -> TradeResult:
        """取消订单"""
        if order_id not in self.orders:
            return TradeResult(
                success=False,
                message="订单不存在"
            )

        order = self.orders[order_id]
        if order.status == "filled":
            return TradeResult(
                success=False,
                message="已成交订单无法取消"
            )

        order.status = "cancelled"
        return TradeResult(
            success=True,
            order_id=order_id
        )

    def get_order(self, symbol: str, order_id: str) -> Optional[Order]:
        """获取订单"""
        return self.orders.get(order_id)

    def get_balance(self, currency: str = None) -> List[AccountBalance]:
        """获取余额"""
        balances = []

        for ccy, bal in self.balances.items():
            if currency and ccy != currency:
                continue

            balances.append(AccountBalance(
                currency=ccy,
                balance=bal,
                available=bal,
                frozen=0.0
            ))

        return balances

    def match_limit_orders(self, symbol: str, price: float):
        """
        模拟限价单匹配

        Args:
            symbol: 交易对
            price: 当前价格
        """
        for order in self.orders.values():
            if order.symbol != symbol or order.status != "pending":
                continue

            # 买单: 价格降到或低于限价单价格时成交
            if order.side == "buy" and price <= order.price:
                self._fill_limit_order(order, price)

            # 卖单: 价格升到或高于限价单价格时成交
            elif order.side == "sell" and price >= order.price:
                self._fill_limit_order(order, price)

    def _fill_limit_order(self, order: Order, execution_price: float):
        """执行限价单"""
        base, quote = order.symbol.split('-')

        if order.side == "buy":
            required_balance = order.quantity * execution_price
            if self.balances.get(quote, 0) < required_balance:
                return

            self.balances[quote] = self.balances.get(quote, 0) - required_balance
            self.balances[base] = self.balances.get(base, 0) + order.quantity

        else:  # sell
            if self.balances.get(base, 0) < order.quantity:
                return

            self.balances[base] = self.balances.get(base, 0) - order.quantity
            self.balances[quote] = self.balances.get(quote, 0) + (order.quantity * execution_price)

        # 更新订单
        order.status = "filled"
        order.filled_qty = order.quantity
        order.filled_price = execution_price
